﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace LitTools
{
    /// <summary>
    /// 对象池
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ObjectPool<T> where T : IObjectPoolItem
    {
        /// <summary>
        /// 数量上限
        /// </summary>
        public int maxSize = 100;
        /// <summary>
        /// 所有实例列表
        /// </summary>
        private List<T> allItems;
        /// <summary>
        /// 回收的实例列表
        /// </summary>
        private List<T> recycleItems;

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <returns></returns>
        protected abstract T CreateInstance();

        /// <summary>
        /// 租借实例
        /// </summary>
        /// <returns></returns>
        public T RentObject()
        {
            T instance;
            if (recycleItems == null
                || recycleItems.Count == 0)
            {
                instance = CreateInstance();
                instance.OnCreate();
                if (allItems == null) allItems = new List<T>();
                allItems.Add(instance);
            }
            else
            {
                instance = recycleItems[0];
                instance.OnBeforeRent();
                recycleItems.RemoveAt(0);
            }
            return instance;
        }

        /// <summary>
        /// 回收实例
        /// </summary>
        /// <param name="instance"></param>
        public void ReturnObject(T instance)
        {
            if (instance == null) return;
            if (allItems.Count >= maxSize)
            {
                //直接释放
                instance.OnRelease();
                allItems.Remove(instance);
            }
            else
            {
                //放入回收池
                if (recycleItems == null) recycleItems = new List<T>();
                recycleItems.Add(instance);
                instance.OnBeforeReturn();
            }
        }

        /// <summary>
        /// 回收所有实例
        /// </summary>
        public void ReturnAll()
        {
            for (int i = 0; i < allItems.Count; i++)
            {
                ReturnObject(allItems[i]);
            }
        }

        /// <summary>
        /// 释放实例
        /// </summary>
        /// <param name="instance"></param>
        public void ReleaseObject(T instance)
        {
            if (allItems != null && allItems.Contains(instance))
            {
                allItems.Remove(instance);
                instance.OnRelease();
            }
            if (recycleItems != null && recycleItems.Contains(instance))
                recycleItems.Remove(instance);
        }

        /// <summary>
        /// 清理对象池
        /// </summary>
        public void ReleaseAll()
        {
            if (allItems != null && allItems.Count > 0)
            {
                for (int i = 0; i < allItems.Count; i++)
                {
                    allItems[i].OnRelease();
                }
                allItems.Clear();
            }
            if (recycleItems != null && recycleItems.Count > 0)
                recycleItems.Clear();
        }
    }
}